import sys
import importlib.util
import inspect
import os
from typing import List

from loguru import logger


def is_PokeRunner_testcase(item):
    """Check if a variable is a PokeRunner testcase class"""
    from pokerunner import PokeRunner

    # TODO: skip referenced testcase
    return bool(
        inspect.isclass(item)
        and issubclass(item, PokeRunner)
        and item.__name__ != "PokeRunner"
    )


def prepare_locust_tests(pytest_files: List[str]) -> List:
    """Prepare locust testcases

    Args:
        pytest_files (List[str]): List of paths to pytest files.

    Returns:
        list: testcase class list
    """

    locust_tests = []

    for pytest_file in pytest_files:
        spec = importlib.util.spec_from_file_location("module.name", pytest_file)
        module = importlib.util.module_from_spec(spec)
        spec.loader.exec_module(module)

        for name, item in vars(module).items():
            if not is_PokeRunner_testcase(item):
                continue

            for _ in range(item.config.weight):
                locust_tests.append(item)

    return locust_tests


def main_locusts():
    """Locusts entrance"""

    if any(arg == "locust" for arg in sys.argv):
        try:
            # Monkey patch all at beginning to avoid RecursionError when running locust.
            # `from gevent import monkey; monkey.patch_all()` will be triggered when importing locust
            from locust import main as locust_main

            print("NOTICE: gevent monkey patches have been applied !!!")
        except ImportError:
            print(
                "Locust is not installed. To install, run:\n\n$ pip install locust"
            )
            sys.exit(1)

    from pokerunner.utils import ga_client

    ga_client.track_event("RunLoadTests", "locust")

    # Avoid printing too much log details in console
    logger.remove()
    logger.add(sys.stderr, level="WARNING")

    sys.argv[0] = "locust"
    if len(sys.argv) == 1:
        sys.argv.extend(["-h"])

    if sys.argv[1] in ["-h", "--help", "-V", "--version"]:
        locust_main.main()

    def get_arg_index(*target_args):
        for arg in target_args:
            if arg not in sys.argv:
                continue

            return sys.argv.index(arg) + 1

        return None

    # Get testcase file path
    testcase_index = get_arg_index("-f", "--locustfile")
    if not testcase_index:
        print("Testcase file is not specified, exit 1.")
        sys.exit(1)

    from pokerunner.make import main_make

    pytest_files = []  # Initialize pytest_files within the function
    testcase_file_path = sys.argv[testcase_index]
    pytest_files = main_make([testcase_file_path])
    if not pytest_files:
        print("No valid testcases found, exit 1.")
        sys.exit(1)

    # Do not replace the user-provided test case file path
    # sys.argv[testcase_index] = os.path.join(os.path.dirname(__file__), "locustfile.py")

    locust_main.main()


if __name__ == "__main__":
    main_locusts()
